/*
 * LogFile.h
 */

#ifndef LOGFILE_H_
#define LOGFILE_H_

#include <exception>
#include <fstream>
#include <sstream>
#include <string>
#include "Mutex.h"
#include "TimeUtils.h"

class LogFileException : public std::exception {
	public:
		explicit LogFileException(const std::string& msg) throw();
		virtual ~LogFileException() throw() {}
		virtual const char* what() const throw();
	private:
		std::string msg;
};

class LogFile {
private:
	bool outMode;
	std::string accessFileName;
	std::fstream accessFile;
	Mutex accessFile_Mutex;

	std::string errorFileName;
	std::fstream errorFile;
	Mutex errorFile_Mutex;

	/** Cierra y remueve un archivo si esta vacio.
	 * @param file Archivo a cerrar y borrar si corresponde
	 * @param fileName Path y nombre del archivo que pasado en file
	 */
	void closeAndRemoveIfEmpty(std::fstream& file, const std::string& fileName);

	/** Lee un archivo y lo carga completamente en memoria
	 * @param text Stream donde cargara los datos leidos
	 * @param file Stream de donde intentará leer datos
	 * @return Verdadero si se pudo realizar la operación
	 */
	bool loadFile(std::stringstream& text, std::fstream& file);
public:
	/** Crea una instancia de la clase para escritura o lectura.
	 * @param accessFilePath Path completo al archivo de log de accesos
	 * @param errorFilePath Path completo al archivo de log de errores
	 * @param writeMode Establece el modo de uso (escritura o lectura)
	 */
	LogFile(const std::string& accessFilePath,
			const std::string& errorFilePath, bool writeMode = false);

	/**
	 * Libera recursos y borra los archivos si están en vacios.
	 */
	virtual ~LogFile();

	/** Loguea la información de acceso del cliente
	 * @param id Id del cliente
	 * @param requestLine Request Line enviado por el cliente
	 * @param statusCode Codigo de status de la respuesta generada
	 */
	void addAccessInfo(const std::string& id, const std::string& requestLine,
			int statusCode);

	/** Loguea el error de archivo no enctrado
	 * @param id Id del cliente
	 * @param resource Path del archivo no encontrado
	 */
	void addFileNotFound(const std::string& id, const std::string& resource);

	/** Loguea cualquier info en el log de accesos
	 * @param info Cadena a agregar al archivo de log
	 */
	void addInfo(const std::string& info);

	/** Loguea errores del sistema en el log de errores
	 * @param error Cadena a agregar al archivo de log
	 */
	void addSystemError(const std::string& error);

	/** Loguea cualquier error de un cliente en el log de errores
	 * @param id Id del cliente
	 * @param error Cadena a agregar al archivo de log
	 */
	void addClientError(const std::string& id, const std::string& error);

	/** Carga el archivo completo de log de accesos.
	 * @param file Stream donde se cargará el archivo leido
	 * @return Verdadero si pudo leerse y cargarse
	 */
	bool getAccessLog(std::stringstream& file);

	/** Carga el archivo completo de log de errores.
	 * @param file Stream donde se cargará el archivo leido
	 * @return Verdadero si pudo leerse y cargarse
	 */
	bool getErrorLog(std::stringstream& file);
};

#endif /* LOGFILE_H_ */
